﻿// Copyright © 2010 Silvestru Iapascurta.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see license.txt for details.
// All other rights reserved.

using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using System.ComponentModel;
using System.Xml;
using System.Data.SQLite;
using FeedDotNet;
using FeedDotNet.Common;

namespace Karoro
{
    partial class KaroroForm
    {
        private void Form1_Load(object sender, EventArgs e)
        {
#if (DEBUG)
    extendedWebBrowser1.ScriptErrorsSuppressed = false;
#else
    extendedWebBrowser1.ScriptErrorsSuppressed = true;
#endif

           foreach (TreeNode node in feedTree.Nodes)
            {
                string[] tag_string = node.Tag.ToString().Split(';');

                if (tag_string[0] == "feed")
                {
                    node.ImageIndex = 0;
                    node.SelectedImageIndex = 0;
                }

                if (tag_string[0] == "folder")
                {
                    node.ImageIndex = 1;
                    node.SelectedImageIndex = 1;
                }
            }

            if (Properties.Settings.Default.updateOnStartup)
                UpdateAll();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            extendedWebBrowser1.Stop();
            CleanTempFiles();
            SaveSettings();

            if (dbDeletes > 0)
                Database.Execute("VACUUM", null);

            foreach (BackgroundWorker x in feed_workers)
            {
                x.Dispose();
            }
        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            Properties.Settings.Default.windowState = this.WindowState;
            if (this.WindowState == FormWindowState.Normal)
            {
                Properties.Settings.Default.size = this.Size;
            }
        }

        private void Form1_LocationChanged(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Normal)
            {
                Properties.Settings.Default.location = this.Location;
            }
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutBox About = new AboutBox();
            About.ShowDialog(this);
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void statusBarToolStripMenuItem_Click(object sender, EventArgs e)
        {
            statusStrip1.Visible = statusStrip1.Visible ? false : true;
        }

        private void menuBarToolStripMenuItem_Click(object sender, EventArgs e)
        {
            menuStrip1.Visible = menuStrip1.Visible ? false : true;
        }

        private void menuStrip1_MenuActivate(object sender, EventArgs e)
        {
            if (!menuStrip1.Visible)
            {
                menuStrip1.Show();
            }
        }

        private void menuStrip1_MenuDeactivate(object sender, EventArgs e)
        {
            if (!menuBarToolStripMenuItem.Checked)
            {
                menuStrip1.Hide();
            }
        }

        private void addFeedToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AddFeedDialog Aff = new AddFeedDialog();
            Aff.AddFeed += new Subscription(AddFeedDialog_Add);
            Aff.ShowDialog(this);
        }

        private void feedTree_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (e.Node != null)
            {
                try
                {
                    FileInfo temp = CreateTemporaryHtml(feedTree.SelectedNode, Properties.Settings.Default.itemsPerPage, 0);

                    extendedWebBrowser1.Navigate(temp.FullName);
                }
                catch (Exception ex)
                {
                    CleanTempFiles();
                    throw ex;
                }
            }
        }

        private void addFolderToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CreateFolder("New Folder");
        }

        private TreeNode CreateFolder(string name)
        {
            TreeNode folder = new TreeNode(name);
            folder.ImageIndex = 1;
            folder.SelectedImageIndex = 1;
            folder.Name = name;
            folder.Tag = String.Format("folder;{0}", Database.CreateFolder(name));

            feedTree.Nodes.Add(folder);
            folder.BeginEdit();

            return folder;
        }

        private void feedTree_DragDrop(object sender, DragEventArgs e)
        {
            Point location = ((TreeView)sender).PointToClient(new Point(e.X, e.Y));
            TreeNode node = (TreeNode)e.Data.GetData(typeof(TreeNode));
            TreeNode destinationNode = ((TreeView)sender).GetNodeAt(location);
            string[] tag_string = ((string)node.Tag).Split(';');
                        
            if (destinationNode != null)
            {
                string[] destination_tag_string = ((string)destinationNode.Tag).Split(';');

                // check if not dragging upon itself, or grandfather, or folder upon another folder
                if (destinationNode == node || node == destinationNode.Parent)
                {
                    return;
                }

                else if (tag_string[0] == "folder")
                {
                    node.TreeView.Nodes.Remove(node);
                    destinationNode.TreeView.Nodes.Insert(destinationNode.Index + 1, node);
                    feedTree.SelectedNode = node;
                    return;
                }

                else if (destination_tag_string[0] == "feed")
                {
                    if (node.Parent == null)
                    {
                        node.TreeView.Nodes.Remove(node);
                    }
                    else
                    {
                        node.Parent.Nodes.Remove(node);
                    }

                    if (destinationNode.Parent == null)
                    {
                        destinationNode.TreeView.Nodes.Insert(destinationNode.Index + 1, node);
                        Database.Execute(String.Format("UPDATE feeds SET folder_id = 0 WHERE feed_id = {0}",tag_string[1]), null);
                        Debug.WriteLine("Condition 1 triggered");
                    }
                    else
                    {
                        // this works
                        destinationNode.Parent.Nodes.Insert(destinationNode.Index + 1, node);
                        string[] destinationParent_tag_string = ((string)destinationNode.Parent.Tag).Split(';');
                        Database.Execute(String.Format("UPDATE feeds SET folder_id = {0} WHERE feed_id = {1}", destinationParent_tag_string[1], tag_string[1]), null);
                        Debug.WriteLine("Condition 2 triggered");
                    }
                }
                // we've dragged onto no node, so we add this at the end
                else
                {
                    node.TreeView.Nodes.Remove(node);
                    destinationNode.Nodes.Add(node);
                    Database.Execute(String.Format("UPDATE feeds SET folder_id = {0} WHERE feed_id = {1}", destination_tag_string[1], tag_string[1]), null);
                    Debug.WriteLine("Condition 3 triggered");
                }
            }
            else
            {
                feedTree.Nodes.Remove(node);
                feedTree.Nodes.Add(node);
                Database.Execute(String.Format("UPDATE feeds SET folder_id = 0 WHERE feed_id = {0}", tag_string[1]), null);
                Debug.WriteLine("Condition 4 triggered");
            }

            feedTree.SelectedNode = node;
        }

        private void feedTree_DragEnter(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Move;
        }

        private void feedTree_ItemDrag(object sender, ItemDragEventArgs e)
        {
            feedTree.SelectedNode = (TreeNode)e.Item;
            feedTree.DoDragDrop(e.Item, DragDropEffects.Move);
        }

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.F9)
            {
                feedsToolStripMenuItem.PerformClick();
            }

            if (e.KeyCode == Keys.F5)
            {
                Update(feedTree.SelectedNode);
            }

            if (e.Control && e.Shift && e.KeyCode == Keys.Tab)
            {
                if (feedTree.Nodes.Count != 0)
                {
                    if (feedTree.SelectedNode != null && feedTree.SelectedNode.Index != feedTree.Nodes[0].Index)
                    {
                        feedTree.SelectedNode = feedTree.SelectedNode.PrevNode;
                    }
                    else
                    {
                        feedTree.SelectedNode = feedTree.Nodes[feedTree.Nodes.Count - 1];
                    }
                }
            }
            else if (e.Control && e.KeyCode == Keys.Tab)
            {
                if (feedTree.Nodes.Count != 0)
                {
                    if (feedTree.SelectedNode != null && feedTree.SelectedNode.Index != feedTree.Nodes.Count - 1)
                    {
                        feedTree.SelectedNode = feedTree.SelectedNode.NextNode;
                    }
                    else
                    {
                        feedTree.SelectedNode = feedTree.Nodes[0];
                    }
                }
            }
        }

        private void feedsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            splitContainer1.Panel1Collapsed = splitContainer1.Panel1Collapsed ? false : true;
        }

        private void feedTree_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                feedTree.SelectedNode = feedTree.GetNodeAt(e.X, e.Y);

                if (feedTree.SelectedNode != null)
                {
                    nodeContextMenu.Show(feedTree, e.Location);
                }
                else
                {
                    treeContextMenu.Show(feedTree, e.Location);
                }
            }
        }

        private void menuItem3_Click(object sender, EventArgs e)
        {
            feedTree.SelectedNode.BeginEdit();
        }

        private void menuItem1_Click(object sender, EventArgs e)
        {
            string[] tag_string = ((string)feedTree.SelectedNode.Tag).Split(';');

            TreeNode prevNode = feedTree.SelectedNode.PrevNode;
            TreeNode nextNode = feedTree.SelectedNode.NextNode;

            if (tag_string[0] == "feed")
            {
                Database.Execute(String.Format("DELETE FROM feeds WHERE feed_id = {0};", tag_string[1]), null);
                dbDeletes++;
            }

            if (tag_string[0] == "folder")
            {
                Database.Execute(String.Format("DELETE FROM folders WHERE folder_id = {0}", tag_string[1]), null);
                dbDeletes++;
            }

            feedTree.SelectedNode.Remove();            

            if (nextNode == null)
            {
                if (prevNode == null)
                {
                    extendedWebBrowser1.Navigate("about:blank");
                }
                else
                {
                    feedTree.SelectedNode = prevNode;
                }
            }
            else
            {
                feedTree.SelectedNode = nextNode;
            }
        }

        private void menuItem2_Click(object sender, EventArgs e)
        {
            Update(feedTree.SelectedNode);
        }

        private void preferencesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            PreferencesDialog Preferences = new PreferencesDialog();
            Preferences.PreferencesChanged += new EventHandler(OnPreferencesChanged);
            Preferences.Themes = Themes.ToArray();
            Preferences.ShowDialog(this);
        }

        private void statusResetTimer_Tick(object sender, EventArgs e)
        {
            karoroStatus.Text = "";
            statusResetTimer.Stop();
        }

        private void splitContainer1_MouseDown(object sender, MouseEventArgs e)
        {
            // get the focused control before the splitter is activated
            focusedControl = HelperFunctions.getFocused(this.Controls);
        }

        private void splitContainer1_MouseUp(object sender, MouseEventArgs e)
        {
            if (focusedControl != null)
            {
                // Return focus and clear the temp variable for 
                // garbage collection
                focusedControl.Focus();
                focusedControl = null;
            }
        }

        private void sourceToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!sourceToolStripMenuItem.Checked)
            {
                sourceToolStripMenuItem.Checked = true;
                dateToolStripMenuItem.Checked = false;
                Properties.Settings.Default.sortByView = 0;
                extendedWebBrowser1.Stop();
                CleanTempFiles();
                ReselectCurrentNode();
            }
        }

        private void dateToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!dateToolStripMenuItem.Checked)
            {
                dateToolStripMenuItem.Checked = true;
                sourceToolStripMenuItem.Checked = false;
                Properties.Settings.Default.sortByView = 1;
                extendedWebBrowser1.Stop();
                CleanTempFiles();
                ReselectCurrentNode();
            }
        }

        private void karoroStatus_TextChanged_1(object sender, EventArgs e)
        {
            if (statusResetTimer.Enabled)
            {
                statusResetTimer.Stop();
                statusResetTimer.Start();
            }
            else
            {
                statusResetTimer.Start();
            }
        }

        private void feedTree_AfterExpand(object sender, TreeViewEventArgs e)
        {
            e.Node.ImageIndex = 2;
            e.Node.SelectedImageIndex = 2;
        }

        private void feedTree_AfterCollapse(object sender, TreeViewEventArgs e)
        {
            e.Node.ImageIndex = 1;
            e.Node.SelectedImageIndex = 1;
        }

        private void extendedWebBrowser1_StatusTextChanged(object sender, EventArgs e)
        {
            karoroStatus.Text = extendedWebBrowser1.StatusText;
        }

        private void exportOPMLToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpmlCategory root = new OpmlCategory();

            foreach (TreeNode node in feedTree.Nodes)
            {
                string[] tag_string = node.Tag.ToString().Split(';');

                if (tag_string[0] == "folder")
                {
                    OpmlCategory folder = new OpmlCategory();
                    folder.Title = node.Text;

                    foreach (TreeNode childNodes in node.Nodes)
                    {
                        folder.Feeds.Add(childNodes.Tag as Feed);
                    }

                    root.Categories.Add(folder);
                }

                if (tag_string[0] == "feed")
                {
                    root.Feeds.Add(node.Tag as Feed);
                }
            }

            if (saveFileAsOpmlDialog.ShowDialog() == DialogResult.OK)
            {
                OpmlManager.Export(root, saveFileAsOpmlDialog.FileName);

                if (OpmlManager.HasErrors)
                {
                    foreach (Exception ex in OpmlManager.GetErrors())
                    {
                        Debug.WriteLine(ex.Message);
                    }
                }
                else
                {
                    karoroStatus.Text = "Feeds exported successfully.";
                    Debug.WriteLine("Feeds exported successfully.");
                }
            }
        }

        private void feedTree_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
        {
            if (e.Label == null || e.Label.Trim().Length == 0)
            {
                e.CancelEdit = true;
            }
            else
            {
                string[] tag_string = e.Node.Tag.ToString().Split(';');

                try
                {
                    if (tag_string[0] == "folder")
                        Database.Execute("UPDATE folders SET title = @label WHERE folder_id = @id", new SQLiteParameter[] { new SQLiteParameter("@label", e.Label), new SQLiteParameter("@id", tag_string[1]) });
                    if (tag_string[0] == "feed")
                        Database.Execute("UPDATE feeds SET title = @label WHERE feed_id = @id", new SQLiteParameter[] { new SQLiteParameter("@label", e.Label), new SQLiteParameter("@id", tag_string[1]) });
                    e.Node.Name = e.Label;
                }
                catch (SQLiteException ex)
                {
                    MessageBox.Show(ex.ErrorCode.ToString());
                }
            }
        }

        private void importOPMLToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (openOpmlFileDialog.ShowDialog() == DialogResult.OK)
            {
                XmlDocument xmlDoc = new XmlDocument();
                try
                {
                    xmlDoc.Load(openOpmlFileDialog.FileName);
                }
                catch (Exception)
                {
                    MessageBox.Show(String.Format("\"{0}\" is not a valid OPML file.", openOpmlFileDialog.FileName), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                if (xmlDoc["opml"]["body"] != null)
                {
                    foreach (XmlNode node in xmlDoc["opml"]["body"].ChildNodes)
                    {
                        if (node.Attributes["xmlUrl"] != null)
                        {
                            FeedWorkerArgs t = new FeedWorkerArgs(node.Attributes["xmlUrl"].InnerText, SubAction.Add, null);
                            AssignWork(t);
                        }
                        else if (node.Attributes["text"] != null)
                        {
                            if (node.HasChildNodes)
                            {
                                TreeNode folder = CreateFolder(node.Attributes["text"].InnerText);

                                foreach (XmlNode cNode in node.ChildNodes)
                                {
                                    if (cNode.Attributes["xmlUrl"] != null)
                                    {
                                        FeedWorkerArgs t = new FeedWorkerArgs(cNode.Attributes["xmlUrl"].InnerText, SubAction.Add, folder);
                                        AssignWork(t);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        private void feedTree_KeyDown(object sender, KeyEventArgs e)
        {
            if (feedTree.SelectedNode != null && e.KeyData == Keys.Delete)
            {
                menuItem1_Click(this, null);
            }
        }

        private void menuItem1_Click_1(object sender, EventArgs e)
        {
            UpdateAll();
        }

        private void extendedWebBrowser1_BeforeNavigate2(object sender, BeforeNavigate2EventArgs e)
        {
            if (Properties.Settings.Default.openInExternal && !e.Url.ToString().Contains("file:///") && (int)e.Flags == 64)
            {
                e.Cancel = true;
                System.Diagnostics.Process.Start(e.Url.ToString());
            }
        }

        private void extendedWebBrowser1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            Form1_KeyDown(this, new KeyEventArgs(e.KeyData));
        }

        private void extendedWebBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e)
        {
            if (Properties.Settings.Default.showInTitle && extendedWebBrowser1.DocumentTitle.Length > 0)
                this.Text = extendedWebBrowser1.DocumentTitle + " - Karoro";

            else if (this.Text != "Karoro")
                this.Text = "Karoro";
        }

        private void hoursToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!hoursToolStripMenuItem.Checked)
            {
                hoursToolStripMenuItem.Checked = true;
                hoursToolStripMenuItem1.Checked = false;
                weekToolStripMenuItem.Checked = false;
                monthToolStripMenuItem.Checked = false;
                anytimeToolStripMenuItem.Checked = false;
                Properties.Settings.Default.timespanView = 0;
                extendedWebBrowser1.Stop();
                CleanTempFiles();
                ReselectCurrentNode();
            }
        }

        private void hoursToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            if (!hoursToolStripMenuItem1.Checked)
            {
                hoursToolStripMenuItem.Checked = false;
                hoursToolStripMenuItem1.Checked = true;
                weekToolStripMenuItem.Checked = false;
                monthToolStripMenuItem.Checked = false;
                anytimeToolStripMenuItem.Checked = false;
                Properties.Settings.Default.timespanView = 1;
                extendedWebBrowser1.Stop();
                CleanTempFiles();
                ReselectCurrentNode();
            }
        }

        private void weekToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!weekToolStripMenuItem.Checked)
            {
                hoursToolStripMenuItem.Checked = false;
                hoursToolStripMenuItem1.Checked = false;
                weekToolStripMenuItem.Checked = true;
                monthToolStripMenuItem.Checked = false;
                anytimeToolStripMenuItem.Checked = false;
                Properties.Settings.Default.timespanView = 2;
                extendedWebBrowser1.Stop();
                CleanTempFiles();
                ReselectCurrentNode();
            }
        }

        private void monthToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!monthToolStripMenuItem.Checked)
            {
                hoursToolStripMenuItem.Checked = false;
                hoursToolStripMenuItem1.Checked = false;
                weekToolStripMenuItem.Checked = false;
                monthToolStripMenuItem.Checked = true;
                anytimeToolStripMenuItem.Checked = false;
                Properties.Settings.Default.timespanView = 3;
                extendedWebBrowser1.Stop();
                CleanTempFiles();
                ReselectCurrentNode();
            }
        }

        private void anytimeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!anytimeToolStripMenuItem.Checked)
            {
                hoursToolStripMenuItem.Checked = false;
                hoursToolStripMenuItem1.Checked = false;
                weekToolStripMenuItem.Checked = false;
                monthToolStripMenuItem.Checked = false;
                anytimeToolStripMenuItem.Checked = true;
                Properties.Settings.Default.timespanView = 4;
                extendedWebBrowser1.Stop();
                CleanTempFiles();
                ReselectCurrentNode();
            }
        }
    }
}
